package ctrutil

import (
    "os"
    "github.com/astaxie/beego/logs"
    "fmt"
    "path/filepath"
    "github.com/astaxie/beego"
    "cloud_worm/util/uconst"
    "cloud_worm/util/umodels"
    "cloud_worm/util/unet"
    "strings"
    "time"
    "net/http"
    _ "net/http/pprof"
    "cloud_worm/util/umodels/mysqldb/dbmanager"
    "cloud_worm/util/umodels/mysqldb"
    "cloud_worm/util/third/ucapital"
)

const (
    SessionUserName = "name"
    SessionUserAvatar = "avatar"
)

const (
    WebIdcNum = 1
)

/**
 任务的状态
 */
const (
    // 任务的状态
    WEAPON_TASK_NO_DO = 0
    WEAPON_TASK_DOING = 1
    WEAPON_TASK_DO_OK = 2
    WEAPON_TASK_DO_FAILED = 3
    WEAPON_TASK_ALERT = 4

    // weapon log的状态
    WEAPON_LOG_DONE = 0
    WEAPON_LOG_FAILED = 1
    WEAPON_LOG_NO_DO = 2
    WEAPON_LOG_DOING = 3

    // 任务类型
    TaskForApplication = 1            // 针对应用的task
    TaskForMachine = 2                // 针对机器的task
    TaskForAll = 3                    // 针对所有在线机器的task
    TaskForIPList = 4                // 针对IP list的task
    TaskForAccessSrv = 5
)

const (
    TaskAllApplication = "<all>"
    TaskSomeIPList = "<ip_list>"
    TaskOneWolServer = "<wolserver>"
)

/**
 文件上传相关的
 */
const (
    UploadWormURL = "/upload/worm"
    UploadWeaponURL = "/upload/weapon"

    TmpWeaponsDir = "/weapons/"
    TmpWormDir = "/worm/"
    TmpDir = "./tmp/"

    ReportDataDir = "/usr/local/worm/file/worm/data"
    AlertReportDir = "data_alerts"
)

func createUploadTmpDir() {
    // 初始化一些缓存目录的创建
    err := os.Mkdir(TmpDir, 0744)
    if err != nil {
        if !os.IsExist(err) {
            logs.Error(fmt.Sprintf("mkdir %s error: %s", TmpDir, err.Error()))
        }
    }
    err = os.Mkdir(filepath.Join(TmpDir, TmpWeaponsDir), 0744)
    if err != nil {
        if !os.IsExist(err) {
            logs.Error(fmt.Sprintf("mkdir %s error: %s", TmpDir, err.Error()))
        }
    }
    err = os.Mkdir(filepath.Join(TmpDir, TmpWormDir), 0744)
    if err != nil {
        if !os.IsExist(err) {
            logs.Error(fmt.Sprintf("mkdir %s error: %s", TmpDir, err.Error()))
        }
    }
}

/**
 @Description：
 */
const (
    UploadSoDir = "./lib/analyzer/"                   // ananlyzer so lib的目录

    AnalyzerFunc = "Analyzer"
    GetOutputFunc = "GetOutput"
)
/**
 @Description：创建lib的目录
 @Param:
 @Return：
 */
func createLibSoDir()  {
    // 初始化目录的创建
    err := os.MkdirAll(UploadSoDir, 0744)
    if err != nil {
        if !os.IsExist(err) {
            logs.Error(fmt.Sprintf("mkdir %s error: %s.", UploadSoDir, err.Error()))
        } else {
            logs.Info(fmt.Sprintf("lib dir '%s' exist.", UploadSoDir))
        }
    } else {
        logs.Info(fmt.Sprintf("lib dir '%s' create ok.", UploadSoDir))
    }
}

func mysqlInit()  {
    config := umodels.DbInfo{
        RunMode: RunMode,
        UserName: beego.AppConfig.String(fmt.Sprintf("%s::mysql.user_name", RunMode)),
        Password: beego.AppConfig.String(fmt.Sprintf("%s::mysql.password", RunMode)),
        Domain: beego.AppConfig.String(fmt.Sprintf("%s::mysql.host", RunMode)),
        Port: beego.AppConfig.String(fmt.Sprintf("%s::mysql.port", RunMode)),
        Database: beego.AppConfig.String(fmt.Sprintf("%s::mysql.database", RunMode)),
    }
    logs.Info(config)
    umodels.OrmInit(config)

    defaultApp := &dbmanager.Application{
        Id: ucapital.DefaultApplyId,
        Name: ucapital.DefaultApplyName,
        Created: time.Now().Unix(),
        Updated: time.Now().Unix(),
        Status: mysqldb.StatusValid,
    }
    if err := defaultApp.Read("id"); err != nil {
        defaultApp.Insert()
    }
    return
}

var RunMode string
func init()  {
    RunMode = beego.AppConfig.String("run_mode")
    logs.Info("run_mode=%s", RunMode)

    if RunMode != uconst.RunModeLocalHost {
        // local dev env，no create tmp/lib dir
        createUploadTmpDir()

        createLibSoDir()
    }

    if RunMode != uconst.RunModeLocalHost {
        _, err := os.Stat(ReportDataDir)
        if err != nil {
            panic(fmt.Sprintf("no report dir: %s", ReportDataDir))
        }
    }

    // mysql初始化
    mysqlInit()
}

func setLocalAddrFilter(localNet string)  {
    for _, item := range strings.Split(localNet, ";") {
        item := strings.TrimSpace(item)
        if len(item) == 0 {
            continue
        }

        filterFunc := func(input string) bool {
            if strings.HasPrefix(input, item) {
                return true
            }
            return false
        }
        unet.RegisterParser(item, filterFunc)
    }
    return
}

var LocalAddress string
func init()  {
    localNet := beego.AppConfig.String("local_net")
    if localNet == "" {
        panic("miss config option 'local_net'")
    }

    setLocalAddrFilter(localNet)

    ips, err := unet.AllIPs()
    if err != nil {
        panic(err)
    }

    LocalAddress = unet.Intranet(ips)
    if LocalAddress == "" {
        panic("get local address failed")
    }
    logs.Info("LocalAddress=%s", LocalAddress)

    return
}

func init()  {
    // 启动pprof
    go func() {
        httpServer := &http.Server{
            Addr: fmt.Sprintf("%s:8089", LocalAddress),
            Handler: nil,
            IdleTimeout: 90 * time.Second,
        }
        logs.Info(fmt.Sprintf("start pprof: (%s:8089)", LocalAddress))
        logs.Info(fmt.Sprintf("http://%s:8089/debug/pprof/", LocalAddress))
        err := httpServer.ListenAndServe()
        if err != nil {
            logs.Error(fmt.Sprintf("start pprof error: %s", err.Error()))
        }
    }()

    return
}